home *** CD-ROM | disk | FTP | other *** search
- #ifndef lint -> Sid = "$Id: util.c,v 1.10.2.1 1999/09/14 20:46:26 lhecking Exp $";
- #endif
-
- /* GNUPLOT - util.c */
-
- /*[
- * Copyright 1986 - 1993, 1998 Thomas Williams, Colin Kelley
- *
- * Permission to use, copy, and distribute this software and its
- * documentation for any purpose with or without fee is hereby granted,
- * provided that the above copyright notice appear in all copies and
- * that both that copyright notice and this permission notice appear
- * in supporting documentation.
- *
- * Permission to modify the software is granted, but not the right to
- * distribute the complete modified source code. Modifications are to
- * be distributed as patches to the released version. Permission to
- * distribute binaries produced by compiling modified sources is granted,
- * provided you
- * 1. distribute the corresponding source modifications from the
- * released version in the form of a patch file along with the binaries,
- * 2. add special version identification to distinguish your version
- * in addition to the base release version number,
- * 3. provide your name and address as the primary contact for the
- * support of your modified version, and
- * 4. retain our contact information in regard to use of the base
- * software.
- * Permission to distribute the released version of the source code along
- * with corresponding source modifications in the form of a patch file is
- * granted with same provisions 2 through 4 for binary distributions.
- *
- * This software is provided "as is" without express or implied warranty
- * to the extent permitted by applicable law.
- ]*/
-
-
- #include "plot.h"
- #include "setshow.h" /* for month names etc */
-
-
- /* TRUE if command just typed; becomes FALSE whenever we
- * send some other output to screen. If FALSE, the command line
- * will be echoed to the screen before the ^ error message.
- */
- TBOOLEAN screen_ok;
-
- static char *num_to_str __PROTO((double r));
- static void parse_esc __PROTO((char *instr));
-
- /*
- * chr_in_str() compares the characters in the string of token number t_num
- * with c, and returns TRUE if a match was found.
- */
- int chr_in_str(t_num, c)
- int t_num;
- int c;
- {
- register int i;
-
- if (!token[t_num].is_token)
- return (FALSE); /* must be a value--can't be equal */
- for (i = 0; i < token[t_num].length; i++) {
- if (input_line[token[t_num].start_index + i] == c)
- return (TRUE);
- }
- return FALSE;
- }
-
-
- /*
- * equals() compares string value of token number t_num with str[], and
- * returns TRUE if they are identical.
- */
- int equals(t_num, str)
- int t_num;
- char *str;
- {
- register int i;
-
- if (!token[t_num].is_token)
- return (FALSE); /* must be a value--can't be equal */
- for (i = 0; i < token[t_num].length; i++) {
- if (input_line[token[t_num].start_index + i] != str[i])
- return (FALSE);
- }
- /* now return TRUE if at end of str[], FALSE if not */
- return (str[i] == NUL);
- }
-
-
-
- /*
- * almost_equals() compares string value of token number t_num with str[], and
- * returns TRUE if they are identical up to the first $ in str[].
- */
- int almost_equals(t_num, str)
- int t_num;
- char *str;
- {
- register int i;
- register int after = 0;
- register int start = token[t_num].start_index;
- register int length = token[t_num].length;
-
- if (!str)
- return FALSE;
- if (!token[t_num].is_token)
- return FALSE; /* must be a value--can't be equal */
- for (i = 0; i < length + after; i++) {
- if (str[i] != input_line[start + i]) {
- if (str[i] != '$')
- return (FALSE);
- else {
- after = 1;
- start--; /* back up token ptr */
- }
- }
- }
-
- /* i now beyond end of token string */
-
- return (after || str[i] == '$' || str[i] == NUL);
- }
-
-
-
- int isstring(t_num)
- int t_num;
- {
-
- return (token[t_num].is_token &&
- (input_line[token[t_num].start_index] == '\'' ||
- input_line[token[t_num].start_index] == '"'));
- }
-
-
- int isanumber(t_num)
- int t_num;
- {
- return (!token[t_num].is_token);
- }
-
-
- int isletter(t_num)
- int t_num;
- {
- return (token[t_num].is_token &&
- ((isalpha((int)input_line[token[t_num].start_index])) ||
- (input_line[token[t_num].start_index] == '_')));
- }
-
-
- /*
- * is_definition() returns TRUE if the next tokens are of the form
- * identifier =
- * -or-
- * identifier ( identifer {,identifier} ) =
- */
- int is_definition(t_num)
- int t_num;
- {
- /* variable? */
- if (isletter(t_num) && equals(t_num + 1, "="))
- return 1;
-
- /* function? */
- /* look for dummy variables */
- if (isletter(t_num) && equals(t_num + 1, "(") && isletter(t_num + 2)) {
- t_num += 3; /* point past first dummy */
- while (equals(t_num, ",")) {
- if (!isletter(++t_num))
- return 0;
- t_num += 1;
- }
- return (equals(t_num, ")") && equals(t_num + 1, "="));
- }
- /* neither */
- return 0;
- }
-
-
-
- /*
- * copy_str() copies the string in token number t_num into str, appending
- * a null. No more than max chars are copied (including \0).
- */
- void copy_str(str, t_num, max)
- char str[];
- int t_num;
- int max;
- {
- register int i = 0;
- register int start = token[t_num].start_index;
- register int count = token[t_num].length;
-
- if (count >= max) {
- count = max - 1;
- FPRINTF((stderr, "str buffer overflow in copy_str"));
- }
-
- do {
- str[i++] = input_line[start++];
- } while (i != count);
- str[i] = NUL;
-
- }
-
- /* length of token string */
- int token_len(t_num)
- int t_num;
- {
- return (token[t_num].length);
- }
-
- /*
- * quote_str() does the same thing as copy_str, except it ignores the
- * quotes at both ends. This seems redundant, but is done for
- * efficency.
- */
- void quote_str(str, t_num, max)
- char str[];
- int t_num;
- int max;
- {
- register int i = 0;
- register int start = token[t_num].start_index + 1;
- register int count;
-
- if ((count = token[t_num].length - 2) >= max) {
- count = max - 1;
- FPRINTF((stderr, "str buffer overflow in quote_str"));
- }
- if (count > 0) {
- do {
- str[i++] = input_line[start++];
- } while (i != count);
- }
- str[i] = NUL;
- /* convert \t and \nnn (octal) to char if in double quotes */
- if (input_line[token[t_num].start_index] == '"')
- parse_esc(str);
- }
-
-
- /*
- * capture() copies into str[] the part of input_line[] which lies between
- * the begining of token[start] and end of token[end].
- */
- void capture(str, start, end, max)
- char str[];
- int start, end;
- int max;
- {
- register int i, e;
-
- e = token[end].start_index + token[end].length;
- if (e - token[start].start_index >= max) {
- e = token[start].start_index + max - 1;
- FPRINTF((stderr, "str buffer overflow in capture"));
- }
- for (i = token[start].start_index; i < e && input_line[i] != NUL; i++)
- *str++ = input_line[i];
- *str = NUL;
- }
-
-
- /*
- * m_capture() is similar to capture(), but it mallocs storage for the
- * string.
- */
- void m_capture(str, start, end)
- char **str;
- int start, end;
- {
- register int i, e;
- register char *s;
-
- e = token[end].start_index + token[end].length;
- *str = gp_realloc(*str, (e - token[start].start_index + 1), "string");
- s = *str;
- for (i = token[start].start_index; i < e && input_line[i] != NUL; i++)
- *s++ = input_line[i];
- *s = NUL;
- }
-
-
- /*
- * m_quote_capture() is similar to m_capture(), but it removes
- quotes from either end if the string.
- */
- void m_quote_capture(str, start, end)
- char **str;
- int start, end;
- {
- register int i, e;
- register char *s;
-
- e = token[end].start_index + token[end].length - 1;
- *str = gp_realloc(*str, (e - token[start].start_index + 1), "string");
- s = *str;
- for (i = token[start].start_index + 1; i < e && input_line[i] != NUL; i++)
- *s++ = input_line[i];
- *s = NUL;
-
- if (input_line[token[start].start_index] == '"')
- parse_esc(*str);
-
- }
-
-
- void convert(val_ptr, t_num)
- struct value *val_ptr;
- int t_num;
- {
- *val_ptr = token[t_num].l_val;
- }
-
- static char *num_to_str(r)
- double r;
- {
- static int i = 0;
- static char s[4][25];
- int j = i++;
-
- if (i > 3)
- i = 0;
-
- sprintf(s[j], "%.15g", r);
- if (strchr(s[j], '.') == NULL &&
- strchr(s[j], 'e') == NULL &&
- strchr(s[j], 'E') == NULL)
- strcat(s[j], ".0");
-
- return s[j];
- }
-
- void disp_value(fp, val)
- FILE *fp;
- struct value *val;
- {
- switch (val->type) {
- case INTGR:
- fprintf(fp, "%d", val->v.int_val);
- break;
- case CMPLX:
- if (val->v.cmplx_val.imag != 0.0)
- fprintf(fp, "{%s, %s}",
- num_to_str(val->v.cmplx_val.real),
- num_to_str(val->v.cmplx_val.imag));
- else
- fprintf(fp, "%s",
- num_to_str(val->v.cmplx_val.real));
- break;
- default:
- int_error("unknown type in disp_value()", NO_CARET);
- }
- }
-
-
- double real(val) /* returns the real part of val */
- struct value *val;
- {
- switch (val->type) {
- case INTGR:
- return ((double) val->v.int_val);
- case CMPLX:
- return (val->v.cmplx_val.real);
- }
- int_error("unknown type in real()", NO_CARET);
- /* NOTREACHED */
- return ((double) 0.0);
- }
-
-
- double imag(val) /* returns the imag part of val */
- struct value *val;
- {
- switch (val->type) {
- case INTGR:
- return (0.0);
- case CMPLX:
- return (val->v.cmplx_val.imag);
- }
- int_error("unknown type in imag()", NO_CARET);
- /* NOTREACHED */
- return ((double) 0.0);
- }
-
-
-
- double magnitude(val) /* returns the magnitude of val */
- struct value *val;
- {
- switch (val->type) {
- case INTGR:
- return ((double) abs(val->v.int_val));
- case CMPLX:
- return (sqrt(val->v.cmplx_val.real *
- val->v.cmplx_val.real +
- val->v.cmplx_val.imag *
- val->v.cmplx_val.imag));
- }
- int_error("unknown type in magnitude()", NO_CARET);
- /* NOTREACHED */
- return ((double) 0.0);
- }
-
-
-
- double angle(val) /* returns the angle of val */
- struct value *val;
- {
- switch (val->type) {
- case INTGR:
- return ((val->v.int_val >= 0) ? 0.0 : Pi);
- case CMPLX:
- if (val->v.cmplx_val.imag == 0.0) {
- if (val->v.cmplx_val.real >= 0.0)
- return (0.0);
- else
- return (Pi);
- }
- return (atan2(val->v.cmplx_val.imag,
- val->v.cmplx_val.real));
- }
- int_error("unknown type in angle()", NO_CARET);
- /* NOTREACHED */
- return ((double) 0.0);
- }
-
-
- struct value *
- Gcomplex(a, realpart, imagpart)
- struct value *a;
- double realpart, imagpart;
- {
- a->type = CMPLX;
- a->v.cmplx_val.real = realpart;
- a->v.cmplx_val.imag = imagpart;
- return (a);
- }
-
-
- struct value *
- Ginteger(a, i)
- struct value *a;
- int i;
- {
- a->type = INTGR;
- a->v.int_val = i;
- return (a);
- }
-
-
- void os_error(str, t_num)
- char str[];
- int t_num;
- {
- #ifdef VMS
- static status[2] =
- {1, 0}; /* 1 is count of error msgs */
- #endif /* VMS */
-
- register int i;
-
- /* reprint line if screen has been written to */
-
- if (t_num != NO_CARET) { /* put caret under error */
- if (!screen_ok)
- fprintf(stderr, "\n%s%s\n", PROMPT, input_line);
-
- for (i = 0; i < sizeof(PROMPT) - 1; i++)
- (void) putc(' ', stderr);
- for (i = 0; i < token[t_num].start_index; i++) {
- (void) putc((input_line[i] == '\t') ? '\t' : ' ', stderr);
- }
- (void) putc('^', stderr);
- (void) putc('\n', stderr);
- }
- for (i = 0; i < sizeof(PROMPT) - 1; i++)
- (void) putc(' ', stderr);
- fputs(str, stderr);
- putc('\n', stderr);
-
- for (i = 0; i < sizeof(PROMPT) - 1; i++)
- (void) putc(' ', stderr);
- if (!interactive) {
- if (infile_name != NULL)
- fprintf(stderr, "\"%s\", line %d: ", infile_name, inline_num);
- else
- fprintf(stderr, "line %d: ", inline_num);
- }
-
-
- #ifdef VMS
- status[1] = vaxc$errno;
- sys$putmsg(status);
- (void) putc('\n', stderr);
- #else /* VMS */
- fprintf(stderr, "(%s)\n\n", strerror(errno));
- #endif /* VMS */
-
- bail_to_command_line();
- }
-
-
- void int_error(str, t_num)
- char str[];
- int t_num;
- {
- register int i;
-
- /* reprint line if screen has been written to */
-
- if (t_num != NO_CARET) { /* put caret under error */
- if (!screen_ok)
- fprintf(stderr, "\n%s%s\n", PROMPT, input_line);
-
- for (i = 0; i < sizeof(PROMPT) - 1; i++)
- (void) putc(' ', stderr);
- for (i = 0; i < token[t_num].start_index; i++) {
- (void) putc((input_line[i] == '\t') ? '\t' : ' ', stderr);
- }
- (void) putc('^', stderr);
- (void) putc('\n', stderr);
- }
- for (i = 0; i < sizeof(PROMPT) - 1; i++)
- (void) putc(' ', stderr);
- if (!interactive) {
- if (infile_name != NULL)
- fprintf(stderr, "\"%s\", line %d: ", infile_name, inline_num);
- else
- fprintf(stderr, "line %d: ", inline_num);
- }
- fputs(str, stderr);
- fputs("\n\n", stderr);
-
- bail_to_command_line();
- }
-
- /* Warn without bailing out to command line. Not a user error */
- void int_warn(str, t_num)
- char str[];
- int t_num;
- {
- register int i;
-
- /* reprint line if screen has been written to */
-
- if (t_num != NO_CARET) { /* put caret under error */
- if (!screen_ok)
- fprintf(stderr, "\n%s%s\n", PROMPT, input_line);
-
- for (i = 0; i < sizeof(PROMPT) - 1; i++)
- (void) putc(' ', stderr);
- for (i = 0; i < token[t_num].start_index; i++) {
- (void) putc((input_line[i] == '\t') ? '\t' : ' ', stderr);
- }
- (void) putc('^', stderr);
- (void) putc('\n', stderr);
- }
- for (i = 0; i < sizeof(PROMPT) - 1; i++)
- (void) putc(' ', stderr);
- if (!interactive) {
- if (infile_name != NULL)
- fprintf(stderr, "\"%s\", line %d: ", infile_name, inline_num);
- else
- fprintf(stderr, "line %d: ", inline_num);
- }
- fprintf(stderr, "warning: %s\n", str);
-
- } /* int_warn */
-
- /* Lower-case the given string (DFK) */
- /* Done in place. */
- void lower_case(s)
- char *s;
- {
- register char *p = s;
-
- while (*p != NUL) {
- if (isupper((int)*p))
- *p = tolower(*p);
- p++;
- }
- }
-
- /* Squash spaces in the given string (DFK) */
- /* That is, reduce all multiple white-space chars to single spaces */
- /* Done in place. */
- void squash_spaces(s)
- char *s;
- {
- register char *r = s; /* reading point */
- register char *w = s; /* writing point */
- TBOOLEAN space = FALSE; /* TRUE if we've already copied a space */
-
- for (w = r = s; *r != NUL; r++) {
- if (isspace((int)*r)) {
- /* white space; only copy if we haven't just copied a space */
- if (!space) {
- space = TRUE;
- *w++ = ' ';
- } /* else ignore multiple spaces */
- } else {
- /* non-space character; copy it and clear flag */
- *w++ = *r;
- space = FALSE;
- }
- }
- *w = NUL; /* null terminate string */
- }
-
-
- static void parse_esc(instr)
- char *instr;
- {
- char *s = instr, *t = instr;
-
- /* the string will always get shorter, so we can do the
- * conversion in situ
- */
-
- while (*s != NUL) {
- if (*s == '\\') {
- s++;
- if (*s == '\\') {
- *t++ = '\\';
- s++;
- } else if (*s == 'n') {
- *t++ = '\n';
- s++;
- } else if (*s == 'r') {
- *t++ = '\r';
- s++;
- } else if (*s == 't') {
- *t++ = '\t';
- s++;
- } else if (*s == '\"') {
- *t++ = '\"';
- s++;
- } else if (*s >= '0' && *s <= '7') {
- int i, n;
- if (sscanf(s, "%o%n", &i, &n) > 0) {
- *t++ = i;
- s += n;
- } else {
- /* int_error("illegal octal number ", c_token); */
- *t++ = '\\';
- *t++ = *s++;
- }
- }
- } else {
- *t++ = *s++;
- }
- }
- *t = NUL;
- }
-